package twilight.companion.entity;

import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import twilight.companion.init.ModEntities;
import twilightforest.init.TFSounds;

import java.util.UUID;

public class SummonSkullEntity extends Entity {
    private static final EntityDataAccessor<Float> ROTATION_SPEED = 
    SynchedEntityData.defineId(SummonSkullEntity.class, EntityDataSerializers.FLOAT);

    private static final EntityDataAccessor<Float> HEIGHT_OFFSET = 
    SynchedEntityData.defineId(SummonSkullEntity.class, EntityDataSerializers.FLOAT);
    
    private static final EntityDataAccessor<Integer> RITUAL_TICKS = 
    SynchedEntityData.defineId(SummonSkullEntity.class, EntityDataSerializers.INT);
    
    private BlockPos centerPos;
    private float baseY;
    private float currentRotation = 0.0F;
    private int maxRitualTicks = 120;
    private int transformTicks = 40;
    private UUID ownerUUID;
    private Player sourcePlayer;
    private boolean creativeMode = false;
    private boolean ritualCompleted = false;
    
    public SummonSkullEntity(EntityType<?> entityType, Level level) {
        super(entityType, level);
        this.noPhysics = true;
    }
    
    public SummonSkullEntity(EntityType<?> entityType, Level level, BlockPos centerPos) {
        this(entityType, level);
        this.centerPos = centerPos;
        this.baseY = centerPos.getY() + 1.2F;
        setPos(centerPos.getX() + 0.5, baseY, centerPos.getZ() + 0.5);
    }
    
    public void setOwnerUUID(UUID uuid) {
        this.ownerUUID = uuid;
    }
    
    public void setSourcePlayer(Player player) {
        this.sourcePlayer = player;
    }
    
    public void setCreativeMode(boolean creative) {
        this.creativeMode = creative;
    }
    
    @Override
    protected void defineSynchedData() {
        entityData.define(ROTATION_SPEED, 2.0F);
        entityData.define(HEIGHT_OFFSET, 0.0F);
        entityData.define(RITUAL_TICKS, 0);
    }
    
    @Override
    public void tick() {
        super.tick();
        
        if (centerPos == null) {
            return;
        }
        
        int currentTicks = entityData.get(RITUAL_TICKS);
        currentTicks++;
        entityData.set(RITUAL_TICKS, currentTicks);
        
        if (!ritualCompleted && currentTicks >= maxRitualTicks) {
            ritualCompleted = true;
        }
        
        if (!ritualCompleted) {
            performRitualMovement(currentTicks);
        } else {
            performTransformMovement(currentTicks - maxRitualTicks);
        }
    }
    
    private void performRitualMovement(int currentTicks) {
        float progress = (float) currentTicks / maxRitualTicks;
        float rotationSpeed = 2.0F + progress * 15.0F;
        entityData.set(ROTATION_SPEED, rotationSpeed);
        float heightOffset;

        if (progress < 0.7F) {
            heightOffset = (progress / 0.7F) * 2.0F;
        } else {
            float fallProgress = (progress - 0.7F) / 0.3F;
            heightOffset = 2.0F * (1.0F - fallProgress);
        }

        entityData.set(HEIGHT_OFFSET, heightOffset);
        currentRotation += rotationSpeed;

        if (currentRotation >= 360.0F) {
            currentRotation -= 360.0F;
        }

        double radius = 0.8 + Math.sin(currentTicks * 0.1) * 0.2;
        double x = centerPos.getX() + 0.5 + Math.cos(Math.toRadians(currentRotation)) * radius;
        double z = centerPos.getZ() + 0.5 + Math.sin(Math.toRadians(currentRotation)) * radius;
        double y = baseY + heightOffset;
        setPos(x, y, z);
    }
    
    private void performTransformMovement(int transformTicks) {
        float transformProgress = (float) transformTicks / this.transformTicks;
        float rotationSpeed = Math.max(1.0F, 17.0F * (1.0F - transformProgress));
        entityData.set(ROTATION_SPEED, rotationSpeed);

        double targetX = centerPos.getX() + 0.5;
        double targetZ = centerPos.getZ() + 0.5;
        double targetY = centerPos.getY() + 1.1;
        
        double currentX = getX();
        double currentZ = getZ();
        double currentY = getY();

        double newX = currentX + (targetX - currentX) * 0.1;
        double newZ = currentZ + (targetZ - currentZ) * 0.1;
        double newY = currentY + (targetY - currentY) * 0.05;
        
        setPos(newX, newY, newZ);
        
        currentRotation += rotationSpeed;
        if (currentRotation >= 360.0F) {
            currentRotation -= 360.0F;
        }
        
        if (transformTicks == this.transformTicks) {
            completeRitual();
            discard();
        }
    }
    
    private void completeRitual() {
        if (!(level() instanceof ServerLevel serverLevel)) {
            return;
        }
        
        Player player = null;
        if (ownerUUID != null) {
            player = serverLevel.getPlayerByUUID(ownerUUID);
        }
        if (player == null && sourcePlayer != null) {
            player = sourcePlayer;
        }
        
        if (player == null) {
            return;
        }

        MiniYetiEntity miniYeti = new MiniYetiEntity(ModEntities.MINI_YETI.get(), level());
        miniYeti.setPos(getX(), getY(), getZ());
        miniYeti.setOwnerUUID(player.getUUID());
        miniYeti.setTame(true);
        miniYeti.setOrderedToSit(false);
        miniYeti.lookAt(player, 180F, 0F);
        
        level().addFreshEntity(miniYeti);
        level().playSound(null, centerPos, TFSounds.ALPHA_YETI_ROAR.get(), SoundSource.BLOCKS, 2.0F, 0.8F);
    }
    
    public float getRotationSpeed() {
        return entityData.get(ROTATION_SPEED);
    }
    
    public float getHeightOffset() {
        return entityData.get(HEIGHT_OFFSET);
    }
    
    public int getRitualTicks() {
        return entityData.get(RITUAL_TICKS);
    }
    
    @Override
    protected void readAdditionalSaveData(CompoundTag tag) {
        if (tag.contains("CenterX")) {
            centerPos = new BlockPos(tag.getInt("CenterX"), tag.getInt("CenterY"), tag.getInt("CenterZ"));
            baseY = tag.getFloat("BaseY");
            currentRotation = tag.getFloat("CurrentRotation");
            maxRitualTicks = tag.getInt("MaxRitualTicks");
        }
        if (tag.contains("OwnerUUID")) {
            ownerUUID = tag.getUUID("OwnerUUID");
        }
        creativeMode = tag.getBoolean("CreativeMode");
    }
    
    @Override
    protected void addAdditionalSaveData(CompoundTag tag) {
        if (centerPos != null) {
            tag.putInt("CenterX", centerPos.getX());
            tag.putInt("CenterY", centerPos.getY());
            tag.putInt("CenterZ", centerPos.getZ());
            tag.putFloat("BaseY", baseY);
            tag.putFloat("CurrentRotation", currentRotation);
            tag.putInt("MaxRitualTicks", maxRitualTicks);
        }
        if (ownerUUID != null) {
            tag.putUUID("OwnerUUID", ownerUUID);
        }
        tag.putBoolean("CreativeMode", creativeMode);
    }
}